@file:Suppress("unused")

package com.virtualightning.mvvm.base

import android.app.Activity
import android.content.Intent
import android.content.pm.PackageManager
import android.os.Build
import android.util.SparseArray
import androidx.lifecycle.ViewModel
import androidx.lifecycle.ViewModelProvider
import androidx.lifecycle.ViewModelStoreOwner
import com.virtualightning.mvvm.tools.ActivityPermissionDeferred
import com.virtualightning.mvvm.tools.ActivityResultDeferred
import com.virtualightning.mvvm.tools.SyncCode
import kotlinx.coroutines.CompletableDeferred
import kotlinx.coroutines.CoroutineScope
import kotlin.coroutines.CoroutineContext

/**
 *  Anchor : Create by CimZzz
 *  Time : 2021/10/09 18:58
 *  虚拟组件
 *  整合 Activity / Fragment 中共用的增强方法, 抽象出统一类集中处理
 */
class ComponentAware(val support: IComponentSupport) {
	///////////////////////////////////////////////////////////////////////////
	// 代码分割线 on 2021/1/25 下午4:20 by CimZzz
	// 以下内容为:
	// ViewModel 相关封装
	///////////////////////////////////////////////////////////////////////////

	///////////////////////////////////////////////////////////////////////////
	// Add by CimZzz on 2021/1/25 下午3:55
	// 自身的 ViewModel Provider
	///////////////////////////////////////////////////////////////////////////
	val viewModelProvider: ViewModelProvider by lazy {
		ViewModelProvider(support.supportViewModelStoreOwner())
	}

	///////////////////////////////////////////////////////////////////////////
	// Add by CimZzz on 2021/1/25 下午4:01
	// 找到对应的 ViewModel
	///////////////////////////////////////////////////////////////////////////
	inline fun <reified T: ViewModel> findViewModel(key: String? = null) : T {
		return if(key == null) {
			viewModelProvider[T::class.java]
		}
		else {
			viewModelProvider[key, T::class.java]
		}
	}

	///////////////////////////////////////////////////////////////////////////
	// Add by CimZzz on 2021/1/25 下午4:01
	// 在父级中找到对应的 ViewModel
	///////////////////////////////////////////////////////////////////////////
	inline fun <reified T: ViewModel> findParentViewModel(key: String? = null) : T {
		return support.supportParentFragment()?.aware?.findViewModel(key) ?: findActivityViewModel(key)
	}

	///////////////////////////////////////////////////////////////////////////
	// Add by CimZzz on 2021/10/9 7:19 PM
	// 找到对应的 Activity ViewModel
	///////////////////////////////////////////////////////////////////////////
	inline fun <reified T: ViewModel> findActivityViewModel(key: String? = null) : T {
		val viewModelProvider = support.supportBaseUI()?.aware?.viewModelProvider ?: viewModelProvider
		return if(key == null) {
			viewModelProvider[T::class.java]
		}
		else {
			viewModelProvider[key, T::class.java]
		}
	}

	///////////////////////////////////////////////////////////////////////////
	// 代码分割线 on 2021/10/12 11:23 AM by CimZzz
	// 以下内容为:
	// 针对接口注册处的封装
	///////////////////////////////////////////////////////////////////////////

	///////////////////////////////////////////////////////////////////////////
	// Add by CimZzz on 2021/10/12 11:13 AM
	// 接口注册处
	///////////////////////////////////////////////////////////////////////////
	private lateinit var interfaceRegistry: HashMap<Class<*>, Any>


	/**
	 * 注册接口信息
	 * @param interfaceCls Class<T> 接口基类
	 * @param entity E 接口对象
	 */
	fun <T, E: T> registerInterface(interfaceCls: Class<T>, entity: E) {
		if(!this::interfaceRegistry.isInitialized) {
			this.interfaceRegistry = HashMap()
		}
		this.interfaceRegistry[interfaceCls] = entity as Any
	}

	/**
	 * 注册接口信息，延迟创建
	 * @param interfaceCls Class<T> 接口基类
	 * @param callback Function1<ComponentAware, E> 实际生成接口对象的回调方法
	 */
	fun <T, E: T> registerInterface(interfaceCls: Class<T>, callback: (ComponentAware) -> E) {
		if(!this::interfaceRegistry.isInitialized) {
			this.interfaceRegistry = HashMap()
		}
		this.interfaceRegistry[interfaceCls] = LazyInitInterface(callback)
	}


	///////////////////////////////////////////////////////////////////////////
	// Add by CimZzz on 2021/10/12 11:33 AM
	// 找到接口实现类
	///////////////////////////////////////////////////////////////////////////
	fun<T> findInterface(interfaceCls: Class<T>) : T? {
		@Suppress("UNCHECKED_CAST")
		if(this::interfaceRegistry.isInitialized) {
			val result = interfaceRegistry[interfaceCls]
			if(result != null) {
				if(interfaceCls.isInstance(result)) {
					return result as T
				}
				if(result is LazyInitInterface<*>) {
					val realResult = result.callback(this) as T
					interfaceRegistry[interfaceCls] = realResult!!
					return realResult
				}
			}
		}
		val parent = support.supportParentFragment() ?: support.supportBaseUI() ?: return null
		if(parent is BaseFragment) {
			return parent.aware.findInterface(interfaceCls)
		}
		if(parent is BaseDialogFragment<*>) {
			return parent.aware.findInterface(interfaceCls)
		}
		if(parent is BaseUI && parent.aware != this) {
			return parent.aware.findInterface(interfaceCls)
		}
		return null
	}




	///////////////////////////////////////////////////////////////////////////
	// 代码分割线 on 2021/10/12 11:22 AM by CimZzz
	// 以下内容为:
	// 针对协程的封装
	///////////////////////////////////////////////////////////////////////////


	///////////////////////////////////////////////////////////////////////////
	// Add by CimZzz on 2021/6/7 11:35 PM
	// ActivityResult 映射表
	///////////////////////////////////////////////////////////////////////////
	val activityResultMap : SparseArray<ActivityResultDeferred<*>> by lazy { SparseArray() }

	///////////////////////////////////////////////////////////////////////////
	// Add by CimZzz on 2021/6/7 11:54 PM
	// ActivityResult 生成序列码
	///////////////////////////////////////////////////////////////////////////
	val activityResultSyncCode : SyncCode by lazy { SyncCode() }


	///////////////////////////////////////////////////////////////////////////
	// Add by CimZzz on 2021/10/9 3:56 PM
	// 启动 Activity 并捕获结果
	///////////////////////////////////////////////////////////////////////////
	inline fun <reified T> openActivityForResult(intent: Intent): ActivityResultDeferred<T> {
		val deferred = registerActivityResult<T>()
		support.supportStartActivityForResult(intent, deferred.requestCode)
		return deferred
	}

	///////////////////////////////////////////////////////////////////////////
	// Add by CimZzz on 2021/6/8 12:01 AM
	// 注册 ActivityResultDeferred
	///////////////////////////////////////////////////////////////////////////
	inline fun <reified T> registerActivityResult() : ActivityResultDeferred<T> {
		val requestCode = activityResultSyncCode.nextCode()
		val deferred = activityResultMap[requestCode] ?: run {
			val newDeferred = ActivityResultDeferred(requestCode, T::class.java, CompletableDeferred())
			activityResultMap.put(requestCode, newDeferred)
			newDeferred
		}

		@Suppress("UNCHECKED_CAST")
		return deferred as ActivityResultDeferred<T>
	}


	///////////////////////////////////////////////////////////////////////////
	// Add by CimZzz on 2021/6/7 11:47 PM
	// 监控 onActivityResult 回调，如果当前 activityResultMap 存在对应 RequestCode，则将数据喂给对应的
	// ActivityResultDeferred
	///////////////////////////////////////////////////////////////////////////
	fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?): Boolean {
		val deferred = activityResultMap[requestCode] ?: return false
		activityResultMap.remove(requestCode)
		if(resultCode == Activity.RESULT_OK) {
			deferred.feed(data?.getSerializableExtra("data"))
		} else {
			deferred.feed(null)
		}
		return true
	}

	///////////////////////////////////////////////////////////////////////////
	// Add by CimZzz on 2021/10/8 5:49 PM
	// Activity 申请权限映射表
	// 当申请成功时，回调中的列表为空
	///////////////////////////////////////////////////////////////////////////
	private lateinit var activityPermissionMap : SparseArray<ActivityPermissionDeferred>

	///////////////////////////////////////////////////////////////////////////
	// Add by CimZzz on 2021/10/8 5:50 PM
	// Activity 权限申请生成序列码
	///////////////////////////////////////////////////////////////////////////
	private val activityPermissionSyncCode : SyncCode by lazy { SyncCode() }

	///////////////////////////////////////////////////////////////////////////
	// Add by CimZzz on 2021/10/8 5:55 PM
	// 动态申请权限
	///////////////////////////////////////////////////////////////////////////
	fun requestPermission(permissions: Array<out String>) : ActivityPermissionDeferred {
		if(!this::activityPermissionMap.isInitialized) {
			activityPermissionMap = SparseArray()
		}
		val deferred = ActivityPermissionDeferred(activityPermissionSyncCode.nextCode(), permissions)
		if(Build.VERSION.SDK_INT < Build.VERSION_CODES.M) {
			deferred.feed(emptyList())
			return deferred
		}
		activityPermissionMap.put(deferred.requestCode, deferred)
		support.supportRequestPermission(permissions, deferred.requestCode)
		return deferred
	}

	///////////////////////////////////////////////////////////////////////////
	// Add by CimZzz on 2021/10/8 5:43 PM
	// 权限申请回调
	///////////////////////////////////////////////////////////////////////////
	fun onRequestPermissionsResult(requestCode: Int, permissions: Array<out String>, grantResults: IntArray): Boolean {
		if(!this::activityPermissionMap.isInitialized) {
			return false
		}
		val deferred = activityPermissionMap[requestCode] ?: return false
		activityPermissionMap.remove(requestCode)
		val deniedList = (grantResults.indices).mapNotNull { index ->
			if(grantResults[index] != PackageManager.PERMISSION_GRANTED) {
				permissions[index]
			}
			else {
				null
			}
		}.toList()
		deferred.feed(deniedList)
		return true
	}

	///////////////////////////////////////////////////////////////////////////
	// Add by CimZzz on 2021/10/9 7:07 PM
	// 销毁全部资源
	///////////////////////////////////////////////////////////////////////////
	fun destroy() {
		if(this::activityPermissionMap.isInitialized) {
			(0 until activityPermissionMap.size()).forEach {
				val value = activityPermissionMap.valueAt(it)
				value.cancel()
			}
			activityPermissionMap.clear()
		}

		if(this.activityResultMap.size() > 0) {
			(0 until activityResultMap.size()).forEach {
				val value = activityResultMap.valueAt(it)
				value.cancel()
			}
			activityResultMap.clear()
		}

		if(this::interfaceRegistry.isInitialized) {
			this.interfaceRegistry.clear()
		}
	}

	///////////////////////////////////////////////////////////////////////////
	// Add by CimZzz on 2021/10/9 7:01 PM
	// 抽象组件需要实现的方法
	///////////////////////////////////////////////////////////////////////////
	interface IComponentSupport {

		///////////////////////////////////////////////////////////////////////////
		// Add by CimZzz on 2021/10/9 7:02 PM
		// 需要提供 startActivityForResult 方法
		///////////////////////////////////////////////////////////////////////////
		fun supportStartActivityForResult(intent: Intent, reqCode: Int)

		///////////////////////////////////////////////////////////////////////////
		// Add by CimZzz on 2021/10/9 7:07 PM
		// 需要提供请求权限方法
		///////////////////////////////////////////////////////////////////////////
		fun supportRequestPermission(permissions: Array<out String>, reqCode: Int)

		///////////////////////////////////////////////////////////////////////////
		// Add by CimZzz on 2021/10/9 7:09 PM
		// 需要提供 ViewModel 存储所有者
		///////////////////////////////////////////////////////////////////////////
		fun supportViewModelStoreOwner(): ViewModelStoreOwner

		///////////////////////////////////////////////////////////////////////////
		// Add by CimZzz on 2021/10/9 7:20 PM
		// 需要提供 Activity
		///////////////////////////////////////////////////////////////////////////
		fun supportBaseUI(): BaseUI?

		///////////////////////////////////////////////////////////////////////////
		// Add by CimZzz on 2021/10/11 6:03 PM
		// 需要提供协程域
		///////////////////////////////////////////////////////////////////////////
		fun supportScope(): CoroutineScope

		///////////////////////////////////////////////////////////////////////////
		// Add by CimZzz on 2021/10/12 3:56 PM
		// 需要提供父 Fragment
		///////////////////////////////////////////////////////////////////////////
		fun supportParentFragment(): BaseFragment? = null
	}

	/**
	 * 延迟生成 Interface
	 */
	private class LazyInitInterface<T> (
		val callback: (ComponentAware) -> T
	)
}
